/*
 * Copyright 2011 Kim Lindhardt Madsen
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package dk.lindhardt.gwt.geie.client.edit;

import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import dk.lindhardt.gwt.geie.client.Validator;
import dk.lindhardt.gwt.geie.shared.Formula;
import dk.lindhardt.gwt.geie.shared.Position;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * User: AnAmuser
 * Date: 25-08-11
 * <p/>
 * A box for editing cell values
 */
public class CellValueEditBox extends Composite {

   private int currentCursorPos;
   private boolean isFormula;
   private List<Validator> validators;
   private Label errorLabel;
   private TextBox textBox;

   public CellValueEditBox() {
      textBox = new TextBox();
      textBox.addStyleName("geie-cell-value-box");
      errorLabel = new Label();
      errorLabel.setVisible(false);
      errorLabel.addStyleName("geie-cell-value-error-label");

      VerticalPanel panel = new VerticalPanel();
      initWidget(panel);
      panel.add(textBox);
      panel.add(errorLabel);

      validators = new ArrayList<Validator>();
      textBox.addKeyDownHandler(
            new KeyDownHandler() {
               public void onKeyDown(KeyDownEvent event) {
                  String value = textBox.getValue();
                  int nativeKeyCode = event.getNativeKeyCode();
                  if (event.isShiftKeyDown() && nativeKeyCode == 48) {
                     isFormula = true;
                  } else {
                     isFormula = value.startsWith("=");
                  }
               }
            });
      textBox.addKeyUpHandler(
            new KeyUpHandler() {
               public void onKeyUp(KeyUpEvent event) {
                  currentCursorPos = textBox.getCursorPos();
               }
            });
   }

   /**
    * Add key down handler to the text box
    * @param keyDownHandler the handler
    */
   public void addKeyDownHandler(KeyDownHandler keyDownHandler) {
      textBox.addKeyDownHandler(keyDownHandler);
   }

   /**
    * Add key up handler to the text box
    * @param keyUpHandler the handler
    */
   public void addKeyUpHandler(KeyUpHandler keyUpHandler) {
      textBox.addKeyUpHandler(keyUpHandler);
   }

   /**
    * Gets the text
    * @return the text
    */
   public String getText() {
      return textBox.getText();
   }

   /**
    * Sets the text
    * @param text the text
    */
   public void setText(String text) {
      textBox.setText(text);
   }

   /**
    * Inserts the position (A reference to another cell) as a variable in the formula.
    * @param position the position of the referenced cell
    */
   public void insertVariable(Position position) {
      String posString = "[" + position.getRow() + "," + position.getColumn() + "]";
      insertText(posString);
   }

   /**
    * Inserts the string in the formula at the current position.
    * @param text the text to insert
    */
   public void insertText(String text) {
      StringBuffer stringBuffer = new StringBuffer(getText());
      stringBuffer.insert(currentCursorPos, text);
      currentCursorPos += text.length();
      setText(stringBuffer.toString());
   }

   /**
    * Regaings focus of the editor
    */
   public void regainFocus() {
      textBox.setFocus(true);
      textBox.setCursorPos(currentCursorPos);
   }

   /**
    * Adds a validator to this editBox
    * @param validator the validator
    */
   public void addValidator(Validator validator) {
      validators.add(validator);
   }

   /**
    * Validates all validators and displays error text if not validated
    * @return validated
    */
   public boolean validate() {
      for (Validator validator : validators) {
         Validator.ValidateResponse response = validator.validate();
         if (Validator.Status.FAIL.equals(response.getStatus())) {
            textBox.addStyleName("geie-cell-value-box-error");
            errorLabel.setText(response.getMessage());
            errorLabel.setHeight("100%");
            errorLabel.setVisible(true);
            return false;
         }
      }
      textBox.removeStyleName("geie-cell-value-box-error");
      errorLabel.setText("");
      errorLabel.setVisible(false);
      errorLabel.setHeight("0%");
      return true;
   }

   /**
    * Sets the value of the edit box to a string representation of the given value
    * @param value
    */
   public void setValue(Serializable value) {
      if (value instanceof String) {
         setText((String) value);
      } else if (value instanceof Double) {
         setText(String.valueOf(value));
      } else if (value instanceof Boolean) {
         setText(String.valueOf(value));
      } else if (value instanceof Date) {
         setText(value.toString());
      } else if (value instanceof Formula) {
         setText("=" + FormulaConverter.convertFormula((Formula) value));
      }
   }

   /**
    * @return is the content of the edit widget a formula
    */
   public boolean isFormula() {
      return isFormula;
   }
}
